﻿using System;
using System.Collections.Generic;
using System.Linq;

using SBPweb.PROvibe.Shared.Library.Base;

namespace SBPweb.PROvibe.Shared.Library.Components
{

    public static class IServiceExtensions
    {
        
        #region ContainsName

        public static bool ContainsName(this IEnumerable<IService> element, string name)
        {
            return element.ContainsName<IService>(name);
        }

        #endregion

        #region ContainsType

        public static bool ContainsType(this IEnumerable<IService> element, Type type)
        {
            return ContainsType<IService>(element, type);
        }

        public static bool ContainsType<TType>(this IEnumerable<IService> element)
           where TType : IService
        {
            return ContainsType<IService, TType>(element);
        }

        public static bool ContainsType<TType>(this IEnumerable<IService> element, Type type)
           where TType : IService
        {
            return ContainsType<IService, TType>(element, type);
        }

        public static bool ContainsType<TSource, TType>(this IEnumerable<TSource> element)
            where TSource : IService
            where TType : TSource
        {
            Type type = typeof(TType);
            return ContainsType<TSource, TType>(element, type);
        }

        public static bool ContainsType<TSource, TType>(this IEnumerable<TSource> element, Type type)
            where TSource : IService
            where TType : TSource
        {
            return element.Any(x => type.IsAssignableFrom(x.GetType()));
        }

        #endregion


        #region FirstByName

        public static IService FirstByName(this IEnumerable<IService> element, string name)
        {
            return element.FirstByName<IService>(name);
        }

        public static TResult FirstByName<TResult>(this IEnumerable<IService> element, string name)
            where TResult : IService
        {
            return element.FirstByName<IService, TResult>(name);
        }

        #endregion

        #region FirstByType

        public static IService FirstByType(this IEnumerable<IService> element, Type type)
        {
            return FirstByType<IService>(element, type);
        }

        public static TResult FirstByType<TResult>(this IEnumerable<IService> element)
            where TResult : IService
        {
            return FirstByType<IService, TResult>(element);
        }

        public static TResult FirstByType<TResult>(this IEnumerable<IService> element, Type type)
            where TResult : IService
        {
            return FirstByType<IService, TResult>(element, type);
        }

        public static TResult FirstByType<TSource, TResult>(this IEnumerable<TSource> element)
            where TSource : IService
            where TResult : TSource
        {
            Type type = typeof(TResult);
            return FirstByType<TSource, TResult>(element, type);
        }

        public static TResult FirstByType<TSource, TResult>(this IEnumerable<TSource> element, Type type)
            where TSource : IService
            where TResult : TSource
        {
            return (TResult)element.FirstOrDefault(x => type.IsAssignableFrom(x.GetType()));
        }

        #endregion


        #region WhereNameIs

        public static IEnumerable<IService> WhereNameIs(this IEnumerable<IService> element, string name)
        {
            return element.WhereNameIs<IService>(name);
        }

        public static IEnumerable<TResult> WhereNameIs<TResult>(this IEnumerable<IService> element, string name)
            where TResult : IService
        {
            return element.WhereNameIs<IService, TResult>(name);
        }

        #endregion

        #region WhereTypeIs

        public static IEnumerable<IService> WhereTypeIs(this IEnumerable<IService> element, Type type)
        {
            return WhereTypeIs<IService>(element, type);
        }

        public static IEnumerable<TResult> WhereTypeIs<TResult>(this IEnumerable<IService> element)
            where TResult : IService
        {
            return WhereTypeIs<IService, TResult>(element);
        }

        public static IEnumerable<TResult> WhereTypeIs<TResult>(this IEnumerable<IService> element, Type type)
            where TResult : IService
        {
            return WhereTypeIs<IService, TResult>(element, type);
        }

        public static IEnumerable<TResult> WhereTypeIs<TSource, TResult>(this IEnumerable<TSource> element)
            where TSource : IService
            where TResult : TSource
        {
            Type type = typeof(TResult);
            return WhereTypeIs<TSource, TResult>(element, type);
        }

        public static IEnumerable<TResult> WhereTypeIs<TSource, TResult>(this IEnumerable<TSource> element, Type type)
            where TSource : IService
            where TResult : TSource
        {
            return element.Where(x => type.IsAssignableFrom(x.GetType())).Cast<TResult>().ToList();
        }

        #endregion

    }

}